﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ecopsy.DataTier;
using System.Collections;
using AgencyEntityLib.Context;

namespace AgencyEntityLib.BaseEntity
{
    /// <summary>
    /// Хранилище значений в деревянном справочнике 
    /// </summary>
    public class TreeDictionaryItemValue : TreeEntitySingle    
    {
        public class Comparer : IEqualityComparer<DictionaryItem>
        {
            #region IEqualityComparer<DictionaryItem> Members

            public bool Equals(DictionaryItem x, DictionaryItem y)
            {
                if (x.Value.Equals(y.Value) && x.ParamID.Equals(y.ParamID))
                    return true;
                else
                    return false;
            }

            public int GetHashCode(DictionaryItem obj)
            {

                Func<string, Int32> f = delegate(string s)
                {
                    Int32 res = 0;
                    foreach (char i in s.ToCharArray())
                    {
                        res = res + (int)i;

                    }
                    return res;
                };
                DictionaryItem v = (DictionaryItem)obj;
                return f(v.ParamID) + f(v.Value.ToString());
            }

            #endregion
        }

        #region Properties
        public TreeDictionaryItemValue() : base() { }

        public TreeDictionaryItemValue(TreeEntitySingle Source)

            : base()
        {
            foreach (TreeEntitySingle item in Source.ChildNodes) { this.ChildNodes.Add(item); }

        }


        public string Name { get; set; }

        /// <summary>
        /// Категория древовидного справочника к которой относиться справочник
        /// </summary>
        public string TreeDictionaryTypeID { get; set; }

        private string _TreeDictionaryFolderID = string.Empty;
        /// <summary>
        /// Папка справочника
        /// </summary>
        public string TreeDictionaryFolderID
        {
            get { return (_TreeDictionaryFolderID.Length == 0 ? AgencyLib_GlobalConstants.TreeDictionaryFolderType_System : _TreeDictionaryFolderID); }
            set { _TreeDictionaryFolderID = value; }
        }

        #endregion

    

        /// <summary>
        /// Добавляет к существующему множеству пар - параметр занчение,коллекцию  value.childnodes
        /// </summary>
        /// <param name="value"></param>
        public void AddValue(TreeDictionaryItemValue value)
        {
            if (value.TreeDictionaryFolderID.ToUpper() != TreeDictionaryFolderID.ToUpper() || value.TreeDictionaryFolderID.ToUpper() != TreeDictionaryFolderID.ToUpper())
            {
                throw new Exception("TreeDictionaryItemValue.add - операция не поддерживается для разнородных справочников");
            }            
            TreeDictionaryItemValue.Comparer cmp = new TreeDictionaryItemValue.Comparer();
            HashSet<DictionaryItem> OldSet = ChildNodes.ToHashSet < DictionaryItem>(cmp);
            HashSet<DictionaryItem> NewSet = value.ChildNodes.ToHashSet<DictionaryItem>(cmp);
            OldSet.UnionWith(NewSet);
            ChildNodes.Clear();
            ChildNodes.Add(OldSet.ToArray<DictionaryItem>());
        }

        public void AddValue(string ValueID)
        {

            TreeDictionaryItemValue v = BuildValue(ValueID);
            if (null == v)
                            return;

            TreeDictionaryItemValue.Comparer cmp = new TreeDictionaryItemValue.Comparer();
            HashSet<DictionaryItem> OldSet = ChildNodes.ToHashSet<DictionaryItem>(cmp);
            HashSet<DictionaryItem> NewSet = v.ChildNodes.ToHashSet<DictionaryItem>(cmp);
            OldSet.UnionWith(NewSet);
            ChildNodes.Clear();
            ChildNodes.Add(OldSet.ToArray<DictionaryItem>());
        }

        public  TreeDictionaryItemValue BuildValue(string ValueID)
        {
            wsDictionary ws = (wsDictionary)AgencyLib_GlobalConstants.CurrentAgency.WS_FactoryList[WS_FactoryList.wsKey_Dictionary];
            TreeDictionaryItem d = ws.GetTreeDictionary(TreeDictionaryFolderID, this.TreeDictionaryTypeID);
            TreeDictionaryItemValue v = d.BuildValue(ValueID);
            return v;

        }

       

        
        /// <summary>
        /// Удалить значение и всю ветку выше значения
        /// </summary>
        /// <param name="value"></param>
        public void RemoveValue(string ValueID)
        {
            // Формируем удалемую ветку 
            TreeDictionaryItemValue v = BuildValue(ValueID);

            HashSet<DictionaryItem>DeletedValSet= v.ValueToHashSet();
            //Вычитаем из множества ChildNodes -  DeletedValSet и формируем коллекцию тех значений что остались
            
            HashSet<DictionaryItem> CurretValue =this.ValueToHashSet ();
            //Вычитаем из текущего множества 
            CurretValue.ExceptWith (DeletedValSet);  
            
            //Так как при вычитании могли погибнуть ветки вышестоящих узлов переформируем результат 
            ChildNodes.Clear();
            ChildNodes.Add(CurretValue.ToArray<DictionaryItem>());            

            Dictionary<string, HashSet<DictionaryItem>> res = ValueAsHashSetCollection();
            res.Remove(ValueID);
            Comparer cmp = new Comparer ();
            HashSet<DictionaryItem> result = new HashSet<DictionaryItem>(cmp);
            
            foreach (HashSet<DictionaryItem> i in res.Values)
            {
                result.UnionWith(i); 
            }
            ChildNodes.Clear();
            ChildNodes.Add(result.ToArray<DictionaryItem>());            
        }

        /// <summary>
        /// Значение как коллекция пересекающихся множеств. Построенных от каждого параметра.
        /// </summary>
        /// <returns></returns>
        protected Dictionary<string, HashSet<DictionaryItem>> ValueAsHashSetCollection()
        {

            Dictionary<string, HashSet<DictionaryItem>> res = new Dictionary<string, HashSet<DictionaryItem>>();
            wsDictionary ws = (wsDictionary)AgencyLib_GlobalConstants.CurrentAgency.WS_FactoryList[WS_FactoryList.wsKey_Dictionary];
            TreeDictionaryItem d = ws.GetTreeDictionary(TreeDictionaryFolderID, ID);
            foreach (DictionaryItem i in this.ChildNodes)
            {
                TreeDictionaryItemValue v= d.BuildValue(i.Value.ToString ());
                 HashSet<DictionaryItem>ValAsSet= v.ValueToHashSet();
                 res.Add(i.Value.ToString(), ValAsSet);  
            }
            return res;


        }

        /// <summary>
        /// Представить ChildNodes как HashSet
        /// </summary>
        /// <returns></returns>
        public HashSet<DictionaryItem> ValueToHashSet()
        {
            TreeDictionaryItemValue.Comparer c = new TreeDictionaryItemValue.Comparer();
            HashSet<DictionaryItem> res = new HashSet<DictionaryItem>(c); 

            ChildNodes.Reset();            
            foreach (DictionaryItem i in ChildNodes)
            {
                res.Add(i); 

            }
            return res;
        }
       
        public void Merge(List<DictionaryItem> Source)
        {
            AgencyEntityLib.BaseEntity.TreeDictionaryItem.DictionaryItemComparer c = new AgencyEntityLib.BaseEntity.TreeDictionaryItem.DictionaryItemComparer();
            List<DictionaryItem> result = this.ChildNodes.ToList<DictionaryItem>();
            IEnumerable r = result.Union(Source, c);
            EntityList rslt = new EntityList();
            this.ChildNodes.Reset();

            this.ChildNodes.Clear();
            foreach (DictionaryItem item in r)
            {
                this.ChildNodes.Add(item);
            }

        }

        /// <summary>
        /// Вернуть значение как строчку
        /// </summary>
        public  virtual  string GetValueAsString() 
        {            
            wsDictionary ws = (wsDictionary)AgencyLib_GlobalConstants.CurrentAgency.WS_FactoryList[WS_FactoryList.wsKey_Dictionary];
            TreeDictionaryItem d = ws.GetTreeDictionary(TreeDictionaryFolderID,this .ID);
            return d.GetValueAsString(this);           
        }


        /// <summary>
        /// Рекурсивно значению Value 
        /// </summary>
        /// <param name="Value"></param>
        /// <param name="List"></param>
        public  bool ValueExists( string Value)
        {
            
            return (null != FindNextItem(this, Value));
        }

        private TreeEntitySingle FindNextItem(TreeEntitySingle Branch, string Value)
        {
            if (null == Branch) return null;
            if (Branch is DictionaryItem)
            {
                if (((DictionaryItem)Branch).Value.ToString() == Value) return Branch;
            }

            Branch.ChildNodes.Reset();
            foreach (object Item in Branch.ChildNodes)
            {
                if (!(Item is TreeEntitySingle)) continue;
                TreeEntitySingle obj = FindNextItem((TreeEntitySingle)Item, Value);
                if (null != obj) return obj;
            }
            Branch.ChildNodes.Reset();
            return null;
        }
    

    }
}